home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 6 / ddj_cspc.zip / WINTER.LST < prev   
File List  |  1989-11-21  |  86KB  |  2,599 lines

  1. _AN AID TO DOCUMENTING C REVISITED_
  2. by Ron Winter
  3.  
  4. [LISTING ONE]
  5.  
  6. /*********************************************************************
  7.                                   cpheader.h
  8.  *********************************************************************/
  9.  
  10. #include <malloc.h>
  11. #include <conio.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15.  
  16. #define  Max_unget_buffer        20000
  17. #define  Max_general_buffers     3000
  18. #define  MAX_functions           5000
  19. /* #define  Max_functions           4000 */
  20. #define  Max_defined_functions   1400
  21. #define  Max_files               1400
  22. #define  Max_Recursion           50
  23.  
  24. #define  false       0
  25. #define  true        1
  26. #define  completed   2
  27.  
  28. #define  Escape      0x1b
  29. #define  Control_z   0x1a
  30.  
  31. /*********************************************************************/
  32. typedef struct the_Pages
  33.    {
  34.    int               on_this_page;
  35.    struct the_Pages  *next_page_ptr;
  36.    }linked_pages_list;
  37. /**********************************************************************/
  38. typedef struct
  39.    {
  40.    char              *functions_name;
  41.    char              *its_filename;
  42.    int               is_referenced;
  43.    int               static_function;
  44.    }function_type;
  45. /**********************************************************************/
  46. typedef struct
  47.    {
  48.    char              *source_filename;
  49.    char              *source_file_comment;
  50.    unsigned int      line_count;
  51.    long              size;
  52.    }file_record_type;
  53. /**********************************************************************/
  54. typedef struct                   /* this is the main data base record */
  55.    {
  56.    file_record_type  *file_record_ptr;
  57.    char              *defined_function;
  58.    function_type     *ptr_to_function_table;
  59.    int               number_of_function_calls;
  60.    linked_pages_list *ptr_to_page_list;
  61.    int               number_of_references;
  62.    int               static_definition;
  63.    int               overlay_number;
  64.    }data_base_record_type;
  65. /**********************************************************************/
  66.  
  67. #if MAIN != 0
  68. /***********************************************************************/
  69.  
  70. function_type              /* 6 */
  71.    **sorted_called_list_ptrs,
  72.    *function_list,
  73.    *function_list_ptr;
  74. int
  75.    Max_functions,
  76.    count_of_functions = 0;
  77. /********************************/
  78. file_record_type           /* 14 */
  79.    *file_record_array,
  80.    *file_record_array_ptr;
  81. int
  82.    count_of_source_files = 0;
  83. /********************************/
  84. data_base_record_type      /* 20 */
  85.    *data_base_array,
  86.    *data_base_array_ptr,
  87.    **array_of_unused_ptrs_to_records,
  88.    **array_of_ptrs_to_records;
  89. int
  90.    count_of_valid_records = 0;
  91. /********************************/
  92.  
  93. char *recursion_array[ Max_Recursion ];
  94. int recursion_depth = 0;
  95.  
  96. char nesting_display_buffer[ Max_general_buffers ];
  97.  
  98. char target[ 40 ] = "main";
  99. FILE *output = NULL;
  100.  
  101. char push_buffer[ Max_unget_buffer ] = { 0, 0, 0, 0 };
  102. char *push_buffer_ptr;
  103.  
  104. char file_comment_buffer[ Max_general_buffers ];
  105. int first_comment;
  106.  
  107. int effective_width;
  108.  
  109. int
  110.    page = 1,
  111.    line = 0,
  112.    defined_page_width =    80,
  113.    defined_page_length =   60,
  114.    defined_left_margin =   1,
  115.    defined_right_margin =  1,
  116.    stats_only =      false,
  117.    g_lib_flag =      false,
  118.    g_comment_flag =  false,
  119.    g_dec_def_flag =  false,
  120.    g_help_flag =     false,
  121.    ibm_flag =        true,
  122.    g_quiet_flag =    false,
  123.    g_tech_flag =     false,
  124.    g_ov_flag =       false,
  125.    g_un_flag =       false,
  126.    target_flag =     false;
  127. int top_of_form_done;
  128. char title[] =
  129. /*       mm/dd/yy0 hh:mm:ss0 */
  130.       { "                    C PRINTER - (c) 1987, 1988 rev. 1.3" };
  131.  
  132. /********************************************************************/
  133.  
  134. #else
  135. /*********************************************************************/
  136.  
  137. extern function_type
  138.    **sorted_called_list_ptrs,
  139.    *function_list,
  140.    *function_list_ptr;
  141. extern file_record_type
  142.    *file_record_array,
  143.    *file_record_array_ptr;
  144. extern data_base_record_type
  145.    *data_base_array,
  146.    *data_base_array_ptr,
  147.    **array_of_unused_ptrs_to_records,
  148.    **array_of_ptrs_to_records;
  149. extern char *recursion_array[ ];
  150. extern int
  151.    count_of_valid_records,
  152.    Max_functions,
  153.    count_of_functions,
  154.    count_of_source_files;
  155. extern int page, line, recursion_depth;
  156. extern int first_comment;
  157. extern char nesting_display_buffer[ ];
  158. extern char top_bottom_line_of_box[ ];
  159. extern FILE *output;
  160. extern char push_buffer[ ];
  161. extern char *push_buffer_ptr;
  162. extern char file_comment_buffer[ ];
  163. extern int defined_page_width;
  164. extern int defined_page_length;
  165. extern int defined_left_margin;
  166. extern int defined_right_margin;
  167. extern int effective_width;
  168. extern char target[ ];
  169. extern int
  170.    stats_only,
  171.    g_lib_flag,
  172.    g_comment_flag,
  173.    g_dec_def_flag,
  174.    g_help_flag,
  175.    ibm_flag,
  176.    g_quiet_flag,
  177.    g_tech_flag,
  178.    g_ov_flag,
  179.    g_un_flag,
  180.    target_flag;
  181. extern int top_of_form_done;
  182. extern char title[];
  183. /*********************************************************************/
  184.  
  185. #endif
  186. /**********************************************************************/
  187.  
  188. [LISTING TWO]
  189.  
  190. /*********************************************************************
  191.                                      cp.c
  192.   
  193. static void near bump_line_count( void );
  194. static void near do_top_of_page( void );
  195. static void near deallocate_arrays( void );
  196. static void near allocate_arrays( void );
  197. static void near initialize_globals( void );
  198. static void near build_records_from_list( FILE * );
  199. static void near sort_the_data_base_array( void );
  200. static void near count_all_defined_references( void );
  201. static void near show_function_relationships( void );
  202. static void near show_line_and_byte_counts( void );
  203. static void near show_sorted_function_list( void );
  204. static void near show_page_references( void );
  205. static void near show_unused_if_any( );
  206. static void near show_library_functions( void );
  207. static void near show_files_leading_comments( );
  208.        int       main( int, char ** );
  209.  
  210.  ***************************************************************************/
  211.  
  212. #define  MAIN  1
  213. #include "cpheader.h"
  214. #include "time.h"
  215.  
  216. extern int  near binary_search_sorted_data_base( char * );
  217. extern void near build_box_parts( int );
  218. extern int  near build_the_data_base( char *, char * );
  219. extern void near check_for_new_page( void );
  220. extern int  near doprint( int );
  221. extern void near nasty( int );
  222. extern void near process_arguments( int, int, char **, int );
  223. extern void near scan_for_static_or_global( int *, int, char *, char * );
  224. extern void near tab_to_left_margin( FILE * );
  225.  
  226. static void near allocate_arrays( void );
  227. static void near build_records_from_list( FILE * );
  228. static void near bump_line_count( void );
  229. static void near count_all_defined_references( void );
  230. static void near deallocate_arrays( void );
  231. static void near do_top_of_page( void );
  232. static void near initialize_globals( void );
  233. static void near show_files_leading_comments( void );
  234. static void near show_function_relationships( void );
  235. static void near show_library_functions( void );
  236. static void near show_line_and_byte_counts( void );
  237. static void near show_page_references( void );
  238. static void near show_sorted_function_list( void );
  239. static void near show_unused_if_any( void );
  240. static void near sort_the_data_base_array( void );
  241.        int       main( int, char ** );
  242.  
  243. /***************************************************************************/
  244.  
  245. static void near bump_line_count( )
  246. {
  247. top_of_form_done = false;
  248. ++line;
  249. check_for_new_page();
  250. tab_to_left_margin( output );
  251. }
  252. /***************************************************************************/
  253. static void near do_top_of_page( )
  254. {
  255. if( !top_of_form_done )
  256.    {
  257.    top_of_form_done = true;
  258.    line = 9999;
  259.    check_for_new_page();
  260.    tab_to_left_margin( output );
  261.    }
  262. }
  263. /***************************************************************************/
  264. static void near deallocate_arrays( )
  265. {
  266. if( function_list )
  267.    free( function_list );
  268. if( file_record_array )
  269.    free( file_record_array );
  270. if( data_base_array )
  271.    free( data_base_array );
  272. if( sorted_called_list_ptrs )
  273.    free( sorted_called_list_ptrs );
  274. if( array_of_ptrs_to_records )
  275.    free( array_of_ptrs_to_records );
  276. }
  277. /***************************************************************************/
  278.  
  279. static void near allocate_arrays( )
  280. {
  281. unsigned long length;
  282.  
  283. length = (unsigned long)Max_functions * sizeof( function_type );
  284. if( length > 65535 )
  285.    {
  286.    (void)printf( "too many called functions ( go to huge model code )\n" );
  287.    exit( 1 );
  288.    }
  289. else
  290.    if(
  291.       !( function_list =
  292.          (function_type *)malloc( (unsigned int)length )
  293.        )
  294.      )
  295.       {
  296.       (void)printf( "No room for function_list\n" );
  297.       exit( 1 );
  298.       }
  299.    else
  300.       {
  301.       if( !g_quiet_flag && g_tech_flag )
  302.          (void)printf( "function list = %lu bytes long\n", length );
  303.       }
  304.  
  305. length = (unsigned long)Max_files * sizeof( file_record_type );
  306. if( length > 65535 )
  307.    {
  308.    (void)printf( "too many files ( go to huge model code )\n" );
  309.    exit( 1 );
  310.    }
  311. else
  312.    if(
  313.       !( file_record_array =
  314.          (file_record_type *)malloc( (unsigned int)length )
  315.        )
  316.      )
  317.       {
  318.       (void)printf( "No room for file_record_array\n" );
  319.       exit( 1 );
  320.       }
  321.    else
  322.       {
  323.       if( !g_quiet_flag && g_tech_flag )
  324.          (void)printf( "file record array = %lu bytes long\n", length );
  325.       }
  326.  
  327. length =
  328.    (unsigned long)Max_defined_functions * sizeof( data_base_record_type );
  329. if( length > 65535 )
  330.    {
  331.    (void)printf( "too many defined functions ( go to huge model code )\n" );
  332.    exit( 1 );
  333.    }
  334. else
  335.    if(
  336.       !( data_base_array =
  337.          (data_base_record_type *)malloc( (unsigned int)length )
  338.        )
  339.      )
  340.       {
  341.       (void)printf( "No room for data_base_array\n" );
  342.       exit( 1 );
  343.       }
  344.    else
  345.       {
  346.       if( !g_quiet_flag && g_tech_flag )
  347.          (void)printf( "data base array = %lu bytes long\n", length );
  348.       }
  349.  
  350. length =
  351.    (unsigned long)Max_defined_functions * sizeof( data_base_record_type * );
  352. if( length > 65535 )
  353.    {
  354.    (void)printf(
  355.             "too many defined functions pointers( go to huge model code )\n"
  356.                );
  357.    exit( 1 );
  358.    }
  359. else
  360.    if(
  361.       !( array_of_ptrs_to_records =
  362.          (data_base_record_type **)malloc( (unsigned int)length )
  363.        )
  364.      )
  365.       {
  366.       (void)printf( "No room for *array_of_ptrs_to_records\n" );
  367.       exit( 1 );
  368.       }
  369.    else
  370.       {
  371.       if( !g_quiet_flag && g_tech_flag )
  372.          (void)printf( "array of ptrs to data base = %lu bytes long\n",
  373.                         length );
  374.       }
  375.  
  376. length = (unsigned long)Max_functions * sizeof( function_type * );
  377. if( length > 65535 )
  378.    {
  379.    (void)printf(
  380.       "too many called function ptrs ( go to huge model code )\n"
  381.                );
  382.    exit( 1 );
  383.    }
  384. else
  385.    if(
  386.       !( sorted_called_list_ptrs =
  387.             (function_type **)malloc( (unsigned int)length )
  388.        )
  389.      )
  390.       {
  391.       (void)printf( "No room for ptr function_list\n" );
  392.       exit( 1 );
  393.       }
  394.    else
  395.       {
  396.       if( !g_quiet_flag && g_tech_flag )
  397.          (void)printf( "sorted called list ptrs = %lu bytes long\n", length );
  398.       }
  399. }
  400. /***************************************************************************/
  401.  
  402. static void near initialize_globals( )
  403. {
  404. int i;
  405. char *cp;
  406.  
  407. function_list_ptr = function_list;
  408. data_base_array_ptr = data_base_array;
  409. file_record_array_ptr = file_record_array;
  410.  
  411. for( i = 0; i < Max_Recursion; ++i )
  412.    recursion_array[ i ] = NULL;
  413. build_box_parts( ibm_flag );
  414. effective_width =             /******** set global output width ***********/
  415.    defined_page_width - defined_left_margin - defined_right_margin;
  416. if( effective_width < 40 )
  417.    {
  418.    (void)printf( "\nThe page width is too narrow( needs > 40 )." );
  419.    exit( 1 );
  420.    }
  421.  
  422. cp = &title[ 0 ];    /* insert date and nice time into title */
  423. (void)_strdate( cp );
  424. title[ 8 ] = ' ';
  425. cp = &title[ 10 ];
  426. (void)_strtime( cp );
  427.  
  428. title[ 15 ] = ' ';   /* knock off seconds */
  429. title[ 16 ] = ' ';   /* put am, pm here */
  430. title[ 17 ] = 'm';
  431. title[ 18 ] = ' ';
  432.  
  433. i = atoi( &title[ 10 ] );  /* f/ military to civilian time */
  434. title[ 16 ] = ( i < 12 )? (char)'a': (char)'p';
  435.  
  436. if( i == 0 )
  437.    i = 12;
  438. if( i >= 13 )
  439.    i -= 12;
  440.  
  441. (void)sprintf( &title[ 10 ], "%2d", i );
  442. title[ 12 ] = ':';
  443.  
  444. if( title[ 10 ] == '0' )
  445.    title[ 10 ] = ' ';
  446. }
  447. /***********************************************************************/
  448. static void near build_records_from_list( stream )
  449. FILE  *stream;
  450. {
  451. char input_list_filename[ 129 ], input_line[ 129 ], overlay_number[ 129 ];
  452. int l;
  453.  
  454. while( !feof( stream ) )
  455.    {
  456.    input_list_filename[ 0 ] = '\0';
  457.    input_line[ 0 ] = '\0';
  458.    overlay_number[ 0 ] = '\0';
  459.    fgets( input_line, 128, stream );   /* ends at \n or eof */
  460.  
  461.    if(
  462.       ( l = strlen( input_line ) ) > 1    /* ie not nul string */
  463.      )
  464.       {
  465.       if( input_line[ l - 1 ] == '\n' )
  466.          input_line[ l - 1 ] = '\0';
  467.  
  468.       l = sscanf( input_line, " %s %s ",
  469.                   input_list_filename, overlay_number
  470.                 );
  471.       if( !g_quiet_flag && g_tech_flag )
  472.          {
  473.          (void)printf( "pathname = %s ", input_list_filename );
  474.          if( l )
  475.             (void)printf( "overlay # = %s ", overlay_number );
  476.          }
  477.       (void)build_the_data_base( input_list_filename, overlay_number );
  478.       }
  479.    }
  480. }
  481. /***************************************************************************/
  482.  
  483. static void near sort_the_data_base_array( )
  484. {
  485. int i, still_sorting_flag;
  486.  
  487. for( i = 0, data_base_array_ptr = data_base_array;
  488.      i < count_of_valid_records;
  489.      ++i
  490.    )
  491.    array_of_ptrs_to_records[ i ] = data_base_array_ptr++;
  492.  
  493. if( !g_quiet_flag )
  494.    {
  495.    (void)printf( "\n\nSorting the function list...\n" );
  496.    (void)printf( " of %d functions\n", count_of_valid_records );
  497.    }
  498. still_sorting_flag = true;
  499. while( still_sorting_flag )
  500.    {
  501.    still_sorting_flag = false;
  502.    if( !g_quiet_flag )
  503.       {
  504.       (void)printf( "." );
  505.       }
  506.    for( i = 0; i < count_of_valid_records - 1; ++i )
  507.       {
  508.       if( strcmp( array_of_ptrs_to_records[ i ]->defined_function,
  509.                   array_of_ptrs_to_records[ i + 1 ]->defined_function ) > 0 )
  510.          {
  511.          still_sorting_flag = true;
  512.          data_base_array_ptr = array_of_ptrs_to_records[ i ];
  513.          array_of_ptrs_to_records[ i ] = array_of_ptrs_to_records[ i + 1 ];
  514.          array_of_ptrs_to_records[ i + 1 ] = data_base_array_ptr;
  515.          }
  516.       }
  517.    }
  518. }
  519. /************************************************************************/
  520.  
  521. static void near count_all_defined_references()
  522. {
  523. register int count;
  524. int found;
  525. register function_type *f_list_ptr;
  526.  
  527. f_list_ptr = function_list;         /* the full list */
  528.  
  529. for( count = 0; count < count_of_functions; ++count )
  530.    {
  531.    found = binary_search_sorted_data_base( f_list_ptr->functions_name );
  532.    if( found >= 0 )
  533.       scan_for_static_or_global( &found,
  534.                                  f_list_ptr->static_function,
  535.                                  f_list_ptr->functions_name,
  536.                                  f_list_ptr->its_filename
  537.                                );
  538.    if( found >= 0 )
  539.       array_of_ptrs_to_records[ found ]->number_of_references +=
  540.          f_list_ptr->is_referenced;
  541.    ++f_list_ptr;        /* for all defined functions */
  542.    }
  543. if( !g_quiet_flag && g_dec_def_flag )
  544.    (void)printf( "\n" );
  545. }
  546. /***************************************************************************/
  547.  
  548. static void near show_function_relationships( )
  549. {
  550. int found;
  551. int record_index;
  552.  
  553. found = binary_search_sorted_data_base( target );/* w/o knowing filename */
  554.                   /* note if static, will find random one if more than */
  555.                   /* one with same name */
  556. if( found >= 0 )
  557.    {
  558.    recursion_depth = 0;
  559.    if( !g_quiet_flag )
  560.       {
  561.       (void)printf( "Checking for usage...\n" );
  562.       }
  563.    count_all_defined_references();
  564.    nesting_display_buffer[ 0 ] = '\0';
  565.    if( !g_quiet_flag )
  566.       {
  567.       (void)printf( "Starting the printout...\n" );
  568.       }
  569.    if( !target_flag )               /* main is only called once */
  570.       array_of_ptrs_to_records[ found ]->number_of_references = 1;
  571.    line = 0;
  572.    if( !stats_only )
  573.       {
  574.       (void)doprint( found );       /* of target function */
  575.       for( record_index = 0;
  576.            record_index < count_of_valid_records;
  577.            ++record_index
  578.          )
  579.          {
  580.          (void)fprintf( output, "\n" );
  581.          ++line;
  582.          if( array_of_ptrs_to_records[ record_index ]->number_of_references >
  583.              1
  584.            )
  585.             (void)doprint( record_index );
  586.          }
  587.       }
  588.    }
  589. else        /* cant find target */
  590.    {
  591.    (void)printf( "cant find %s, exitting\n", target );
  592.    exit( 1 );
  593.    }
  594. }
  595. /***************************************************************************/
  596.  
  597. static void near show_line_and_byte_counts( )
  598. {
  599. long int total_byte_count;
  600. long int total_line_count;
  601. int i;
  602.  
  603. file_record_array_ptr = file_record_array;
  604.  
  605. do_top_of_page();
  606. (void)fprintf( output, "File statistics:\n" );
  607. bump_line_count();
  608. total_byte_count = 0l;
  609. total_line_count = 0l;
  610. for( i = 0; i < count_of_source_files; ++i )
  611.    {
  612.    (void)fprintf( output,
  613.                   "%-40s - %8u lines, %12ld bytes\n",
  614.                   file_record_array_ptr->source_filename,
  615.                   file_record_array_ptr->line_count,
  616.                   file_record_array_ptr->size
  617.                 );
  618.    bump_line_count();
  619.  
  620.    total_byte_count += file_record_array_ptr->size;
  621.    total_line_count += file_record_array_ptr->line_count;
  622.    ++file_record_array_ptr;
  623.    }
  624. (void)fputc( '\n', output );
  625. bump_line_count();
  626. (void)fprintf( output, "Totals:\n" );
  627. bump_line_count();
  628. /********                       "%-40s - %8u lines, %12ld bytes\n", *******/
  629. (void)fprintf( output, "%4d files%-30s - %8ld lines, %12ld bytes\n",
  630.                count_of_source_files, " ", total_line_count, total_byte_count
  631.              );
  632. bump_line_count();
  633. (void)fputc( '\n', output );
  634. bump_line_count();
  635. (void)fprintf( output,
  636.                " %d defined functions found.\n", count_of_valid_records
  637.              );
  638. bump_line_count();
  639. (void)fprintf( output, "Averages:\n" );
  640. bump_line_count();
  641. (void)fprintf( output,
  642.                "%6d lines/file, %6d functions/file, %6d lines/function\n",
  643.                (int)( total_line_count / count_of_source_files ),
  644.                (int)( count_of_valid_records / count_of_source_files ),
  645.                (int)( total_line_count / count_of_valid_records )
  646.              );
  647. }
  648. /***************************************************************************/
  649.  
  650. static void near show_sorted_function_list( )
  651. {
  652. int i, record_index;
  653. long reference_total = 0;
  654.  
  655. do_top_of_page();
  656.  
  657. (void)fprintf( output, "Function index:\n" );
  658. bump_line_count();
  659.  
  660. if( g_ov_flag )
  661.    (void)fprintf( output, "%-39s %-28s %s %s\n",
  662.                   "function", "in file", "ov#", "refs" );
  663. else
  664.    (void)fprintf( output, "%-39s %-28s    %s\n",
  665.                   "function", "in file", "refs" );
  666.  
  667. bump_line_count();
  668.  
  669. for( i = 0; i < effective_width; ++i )
  670.    (void)fputc( '_', output );
  671. (void)fprintf( output, "\n" );
  672. bump_line_count();
  673.  
  674. for( record_index = 0;
  675.      record_index < count_of_valid_records;
  676.      ++record_index
  677.    )
  678.    {
  679.    data_base_array_ptr = array_of_ptrs_to_records[ record_index ];
  680.    if( data_base_array_ptr->number_of_references > 0 )
  681.       {   
  682.       if( g_ov_flag && data_base_array_ptr->overlay_number )
  683.          (void)fprintf( output, "%-7s%-32s %-28s %3d %d\n",
  684.                         ( data_base_array_ptr->static_definition )?
  685.                         "static": "",
  686.                         data_base_array_ptr->defined_function,
  687.                   ( data_base_array_ptr->file_record_ptr )->source_filename,
  688.                         data_base_array_ptr->overlay_number,
  689.                         data_base_array_ptr->number_of_references
  690.                       );
  691.       else
  692.          (void)fprintf( output, "%-7s%-32s %-28s     %d\n",
  693.                         ( data_base_array_ptr->static_definition )?
  694.                         "static": "",
  695.                         data_base_array_ptr->defined_function,
  696.                   ( data_base_array_ptr->file_record_ptr )->source_filename,
  697.                         data_base_array_ptr->number_of_references
  698.                       );
  699.       reference_total += (long)data_base_array_ptr->number_of_references;
  700.       bump_line_count();
  701.       }
  702.    }
  703. (void)fprintf( output, "%-7s%-32s %-28s     %s\n",
  704.                " ", " ", " ", "____"
  705.              );
  706. bump_line_count();
  707. (void)fprintf( output, "%-7s%-32s %-28s     %ld\n",
  708.                " ", " ", "total ", reference_total
  709.              );
  710. bump_line_count();
  711. }
  712. /***************************************************************************/
  713.  
  714. static void near show_page_references( )
  715. {
  716. int pmax;          /* max x ref columns */
  717. int i, pcnt;
  718. linked_pages_list *p;
  719.  
  720. if( !stats_only && ( defined_page_length > 0 ) )
  721.    {
  722.    pmax = (int)( effective_width - 7 - 32 - 2 ) / 5;
  723.    do_top_of_page();
  724.    (void)fprintf( output, "Function cross reference:\n" );
  725.    bump_line_count();
  726.  
  727.    for( i = 0; i < count_of_valid_records; ++i )
  728.       {
  729.       data_base_array_ptr = array_of_ptrs_to_records[ i ];
  730.       if( data_base_array_ptr->number_of_references > 0 )
  731.          {
  732.          (void)fprintf( output, "%-7s%-32s- ",
  733.                         ( data_base_array_ptr->static_definition )?
  734.                         "static": "",
  735.                         data_base_array_ptr->defined_function );
  736.          p = data_base_array_ptr->ptr_to_page_list;
  737.          if( p )
  738.             {
  739.             pcnt = 0;
  740.             while( p->next_page_ptr )
  741.                {
  742.                (void)fprintf( output, "%4d,", p->on_this_page );
  743.                p = p->next_page_ptr;
  744.                ++pcnt;
  745.                if( pcnt >= pmax )
  746.                   {
  747.                   (void)fputc( '\n', output );
  748.                   bump_line_count();
  749.                   (void)fprintf( output, "%7s%32s  ", " ", " " );
  750.                   pcnt = 0;
  751.                   }
  752.                }
  753.             (void)fprintf( output, "%4d\n", p->on_this_page );
  754.             }
  755.          else
  756.             (void)fprintf( output, "\n" );
  757.          bump_line_count();
  758.          }
  759.       }
  760.    }
  761. }
  762. /***************************************************************************/
  763.  
  764. static void near show_unused_if_any( )
  765. {
  766. int i, unused_count, unused_index, count, still_sorting_flag;
  767. data_base_record_type **unused_list_ptr_ptr, *unused_list_ptr;
  768.  
  769. do_top_of_page();
  770. (void)fprintf( output, "Un-used function list:\n" );
  771. bump_line_count();
  772.  
  773. unused_count = 0;
  774. for( i = 0; i < count_of_valid_records; ++i )
  775.    {
  776.    data_base_array_ptr = array_of_ptrs_to_records[ i ];
  777.    if( !data_base_array_ptr->number_of_references )
  778.       {
  779.       ++unused_count;
  780.       if( !g_un_flag )
  781.          {
  782.          (void)fprintf( output,
  783.                         "%-7s%-32s- %-33s\n",
  784.                         ( data_base_array_ptr->static_definition )?
  785.                         "static": "",
  786.                         data_base_array_ptr->defined_function,
  787.                      ( data_base_array_ptr->file_record_ptr )->source_filename
  788.                       );
  789.          bump_line_count();
  790.          }
  791.       }
  792.    }
  793. if( g_un_flag )               /* show sorted */
  794.    {
  795.    if( unused_count )
  796.       {
  797.       if(
  798.          !( array_of_unused_ptrs_to_records =
  799.             (data_base_record_type **)malloc( (unsigned int)unused_count )
  800.           )
  801.         )
  802.          (void)printf( "No room for *array_of_unused_ptrs_to_records\n" );
  803.       else
  804.          {
  805.          unused_index = 0;
  806.          for( i = 0; i < count_of_valid_records; ++i )
  807.             {
  808.             data_base_array_ptr = array_of_ptrs_to_records[ i ];
  809.             if( !data_base_array_ptr->number_of_references )
  810.                {                    /* first just collect them */
  811.                array_of_unused_ptrs_to_records[ unused_index++ ] =
  812.                   data_base_array_ptr;
  813.                }
  814.             }                 /* so now there are unused_index of them */
  815.          unused_list_ptr_ptr = array_of_unused_ptrs_to_records;
  816.          still_sorting_flag = true;
  817.          if( unused_count > 1 )
  818.             {
  819.             while( still_sorting_flag )
  820.                {
  821.                still_sorting_flag = false;
  822.                if( !g_quiet_flag && g_tech_flag )
  823.                   (void)printf( ".%d   \r", count );
  824.                for( count = 0; count < unused_count - 1; ++count )
  825.                   {
  826.                   if( strcmp( unused_list_ptr_ptr[ count ]->
  827.                               file_record_ptr->source_filename,
  828.                               unused_list_ptr_ptr[ count + 1 ]->
  829.                               file_record_ptr->source_filename
  830.                             ) > 0
  831.                     )
  832.                      {
  833.                      still_sorting_flag = true;
  834.                      unused_list_ptr = unused_list_ptr_ptr[ count ];
  835.                      unused_list_ptr_ptr[ count ] =
  836.                         unused_list_ptr_ptr[ count + 1 ];
  837.                      unused_list_ptr_ptr[ count + 1 ] = unused_list_ptr;
  838.                      }
  839.                   }
  840.                }
  841.             }
  842.          for( i = 0; i < unused_count; ++i )
  843.             {
  844.             (void)fprintf( output,
  845.                            "%-7s%-32s- %-33s\n",
  846.                            ( unused_list_ptr_ptr[ i ]->static_definition )?
  847.                            "static": "",
  848.                            unused_list_ptr_ptr[ i ]->defined_function,
  849.                ( unused_list_ptr_ptr[ i ]->file_record_ptr )->source_filename
  850.                          );
  851.             bump_line_count();
  852.             }
  853.          }
  854.       }
  855.    }
  856. if( !unused_count )
  857.    {
  858.    tab_to_left_margin( output );
  859.    (void)fprintf( output, "No un-used functions in the list.\n" );
  860.    bump_line_count();
  861.    }
  862. else
  863.    {
  864.    (void)fprintf( output, "%-7s%-39s- %d\n", "", "totals", unused_count );
  865.    bump_line_count();
  866.    }
  867. }
  868. /************************************************************************/
  869.  
  870. static void near show_library_functions( )
  871. {
  872. register int count;
  873. int found, total, still_sorting_flag, x_count, final_count, final_call;
  874. function_type **f_list_ptr_ptr, *f_list_ptr;
  875.  
  876. if( g_lib_flag )
  877.    {
  878.    if( !g_quiet_flag && g_tech_flag )
  879.       (void)printf( "collecting library functions...\n" );
  880.    do_top_of_page();
  881.    (void)fprintf( output, "Library functions:\n" );
  882.    bump_line_count();
  883.  
  884.    total = 0;
  885.    f_list_ptr = function_list;
  886.    for( count = 0; count < count_of_functions; ++count )
  887.       {
  888.       if( !f_list_ptr->static_function )
  889.          {
  890.          if(
  891.             ( found =
  892.               binary_search_sorted_data_base( f_list_ptr->functions_name )
  893.             ) < 0
  894.            )
  895.             sorted_called_list_ptrs[ total++ ] = f_list_ptr;
  896.          }
  897.       ++f_list_ptr;        /* for all called functions */
  898.       }
  899.  
  900.    if( !g_quiet_flag && g_tech_flag )
  901.       (void)printf( "gathering identical library functions...\n" );
  902.    final_count = total;    /* number of calls to be collected and sorted */
  903.    f_list_ptr_ptr = sorted_called_list_ptrs;
  904.    for( count = 0; count < ( total - 1 ); ++count )
  905.       {
  906.       for( x_count = count + 1; x_count < total; ++x_count )
  907.          {
  908.          if( ( f_list_ptr_ptr[ count ]->functions_name[ 0 ] != '\0' ) &&
  909.              !strcmp( f_list_ptr_ptr[ count ]->functions_name,
  910.                       f_list_ptr_ptr[ x_count ]->functions_name )
  911.            )
  912.             {
  913.             f_list_ptr_ptr[ count ]->is_referenced +=
  914.                f_list_ptr_ptr[ x_count ]->is_referenced;
  915.             f_list_ptr_ptr[ x_count ]->functions_name[ 0 ] = '\0';
  916.             --final_count;
  917.             }
  918.          }
  919.       }
  920.  
  921.    if( !g_quiet_flag && g_tech_flag )
  922.       {
  923.       (void)printf( "\nSorting the library function calls...\n" );
  924.       }
  925.  
  926.    f_list_ptr_ptr = sorted_called_list_ptrs;
  927.    still_sorting_flag = true;
  928.    while( still_sorting_flag )
  929.       {
  930.       still_sorting_flag = false;
  931.       if( !g_quiet_flag && g_tech_flag )
  932.          (void)printf( ".%d   \r", count );
  933.       for( count = 0; count < total - 1; ++count )
  934.          {
  935.          if( strcmp( f_list_ptr_ptr[ count ]->functions_name,
  936.                      f_list_ptr_ptr[ count + 1 ]->functions_name ) > 0 )
  937.             {
  938.             still_sorting_flag = true;
  939.             f_list_ptr = f_list_ptr_ptr[ count ];
  940.             f_list_ptr_ptr[ count ] = f_list_ptr_ptr[ count + 1 ];
  941.             f_list_ptr_ptr[ count + 1 ] = f_list_ptr;
  942.             }
  943.          }
  944.       }
  945.    if( !g_quiet_flag && g_tech_flag )
  946.       (void)printf( "\n" );
  947.  
  948.    (void)fprintf( output, "%-32s %-28s\n",
  949.                   "library function", "calls" );
  950.    bump_line_count();
  951.  
  952.    for( count = 0; count < effective_width; ++count )
  953.       (void)fputc( '_', output );
  954.    (void)fprintf( output, "\n" );
  955.    bump_line_count();
  956.  
  957.    final_call = 0;
  958.    f_list_ptr_ptr = sorted_called_list_ptrs;
  959.    for( count = 0; count < total; ++count )
  960.       {
  961.       if( ( *f_list_ptr_ptr )->functions_name[ 0 ] != '\0' )
  962.          {
  963.          (void)fprintf( output, "%-32s %d\n",
  964.                         ( *f_list_ptr_ptr )->functions_name,
  965.                         ( *f_list_ptr_ptr )->is_referenced
  966.                       );
  967.          final_call += ( *f_list_ptr_ptr )->is_referenced;
  968.          bump_line_count();
  969.          }
  970.       ++f_list_ptr_ptr;
  971.       }
  972.    (void)fprintf( output, "Totals:\n" );
  973.    bump_line_count();
  974.    (void)fprintf( output, "%6d %-25s %d calls.\n",
  975.                   final_count, "library functions,", final_call
  976.                 );
  977.    bump_line_count();
  978.    }
  979. }
  980. /************************************************************************/
  981.  
  982. static void near show_files_leading_comments( )
  983. {
  984. int i;
  985. char *cp;
  986.  
  987. if( g_comment_flag )
  988.    {
  989.    do_top_of_page();
  990.    (void)fprintf( output, "File comments:\n" );
  991.    bump_line_count();
  992.    file_record_array_ptr = file_record_array;
  993.    for( i = 0; i < count_of_source_files; ++i )
  994.       {
  995.       (void)fprintf( output, "%40s\n",
  996.                      file_record_array_ptr->source_filename
  997.                    );
  998.       bump_line_count();
  999.       cp = file_record_array_ptr->source_file_comment;
  1000.       while( *cp )
  1001.          {
  1002.          (void)fprintf( output, "%c", *cp );
  1003.          if( *++cp == '\n' )
  1004.             {
  1005.             bump_line_count();
  1006.             }
  1007.          }
  1008.       ++file_record_array_ptr;   
  1009.       do_top_of_page();          /* one page per comment at least */
  1010.       }
  1011.    }
  1012. }
  1013. /**********************************************************************/
  1014.  
  1015. int main( argc, argv )
  1016. char **argv;
  1017. int argc;
  1018. {
  1019. int   index, in_error = false, out_error = false;
  1020. FILE  *stream;
  1021.  
  1022. nasty( argc );
  1023.  
  1024. (void)printf( "\ncp - ver. 1.3,  (C)1987, 1988  Stewart A. Nutter\n" );
  1025. (void)printf( "    extended and corrected by  Ron Winter\n" );
  1026.  
  1027. index = 1;
  1028. if( !( stream = fopen( argv[ index ], "rt" ) ) )
  1029.    in_error = true;
  1030. else
  1031.    ++index;
  1032. if(
  1033.    ( argc > index ) &&
  1034.    (
  1035.     ( argv[ index ][ 0 ] != '/' ) && ( argv[ index ][ 0 ] != '-' )
  1036.    )
  1037.   )
  1038.    {
  1039.    output = fopen( argv[ 2 ], "w+" );     /******* wt+ <<<<<<<< ******/
  1040.    ++index;
  1041.    }
  1042. else
  1043.    output = fopen( "prn", "w+" );         /******** wt+ <<<<<< ********/
  1044.  
  1045. if( !output )
  1046.    out_error = true;
  1047.  
  1048. Max_functions = MAX_functions;
  1049. process_arguments( index, argc, argv, in_error || out_error );
  1050. if( in_error )
  1051.    {
  1052.    (void)printf( "\n can't open input list %s\n", argv[ 1 ] );
  1053.    exit( 1 );
  1054.    }
  1055. if( out_error )
  1056.    {
  1057.    (void)printf( "\n can't open output file, error %s\n", strerror( errno ) );
  1058.    exit( 1 );
  1059.    }
  1060. allocate_arrays( );
  1061. initialize_globals( );
  1062. (void)printf( "\n" );
  1063.  
  1064. build_records_from_list( stream );
  1065. sort_the_data_base_array( );
  1066. if( !g_quiet_flag )
  1067.    {
  1068.    (void)printf( "\n" );
  1069.    }
  1070. top_of_form_done = false;
  1071. show_function_relationships( );
  1072. show_page_references( );
  1073. show_line_and_byte_counts( );
  1074. show_sorted_function_list( );
  1075. show_unused_if_any( );
  1076. show_library_functions( );
  1077. show_files_leading_comments( );
  1078. deallocate_arrays( );
  1079.  
  1080. /************* done *****************/
  1081. (void)fprintf( output, "%c", 0x0c );   /* ff */
  1082.  
  1083. return false;     /* ok */
  1084. }
  1085. /********************************************************************/
  1086.  
  1087.  
  1088. [LISTING THREE]
  1089.  
  1090. /***********************************************************************
  1091.                                    cpinput.c
  1092.        void near nasty( int );
  1093.        void near process_arguments( int, int, char **, int );
  1094. ************************************************************************/
  1095. #define  MAIN  0
  1096. #include "cpheader.h"
  1097.  
  1098.        void near nasty( int );
  1099.        void near process_arguments( int, int, char **, int );
  1100. /************************************************************************/
  1101.  
  1102. void near nasty( argc )
  1103. int argc;
  1104. {
  1105. if( argc < 2 )
  1106.    {
  1107.    (void)printf( "\ncp listfile [ outfile ] [\n" );
  1108.    (void)printf(
  1109.    "     /p:nn /w:nn /m:nn /r:nn /t:main /f:nnnn\n"
  1110.                );
  1111.    (void)printf(
  1112.    "     /l /n /s /q /d /c /h /x\n"
  1113.                );
  1114.    (void)printf(   "                        ]\n\n" );
  1115.    (void)printf(
  1116.    "     outfile            = prn\n" );
  1117.    (void)printf(
  1118.    "    p: page length      = %3d   [ 0, 50 -255 ]\n", defined_page_length
  1119.                );
  1120.    (void)printf(
  1121.    "     w: page width      = %3d   [ 80 - 255 ]\n", defined_page_width
  1122.                );
  1123.    (void)printf(
  1124.    "     m: left margin     = %2d    [ 0 - 30 ]\n", defined_left_margin
  1125.                );
  1126.    (void)printf(
  1127.    "     r: right margin     = %2d    [ 0 - 30 ]\n", defined_right_margin
  1128.                );
  1129.    (void)printf(
  1130.    "     t: target function  = %s\n", target
  1131.                );
  1132.    (void)printf(
  1133.    "     f: # of function calls = %4d    [ 2 - 5461 ]\n", MAX_functions
  1134.                );
  1135.    (void)printf(
  1136.    "     n: normal characters( ie not ibm character graphics )\n"
  1137.                );
  1138.    (void)printf(
  1139.    "     l  output library functions\n"
  1140.                );
  1141.    (void)printf(
  1142.    "     c  output file\'s 1st comment\n"
  1143.                );
  1144.    (void)printf(
  1145.    "     s  output statistics only\n"
  1146.                );
  1147.    (void)printf(
  1148.    "     d  show declarations and definitions\n"
  1149.                );
  1150.    (void)printf(
  1151.    "     o  show overlay information\n"
  1152.                );
  1153.    (void)printf(
  1154.    "     u  show unused sorted by filename\n"
  1155.                );
  1156.    (void)printf(
  1157.    "     q  show no messages\n"
  1158.                );
  1159.    (void)printf(
  1160.    "     h  show more help\n"
  1161.                );
  1162.    (void)printf(
  1163.    "     x  show tech info\n"
  1164.                );
  1165.  
  1166.    (void)printf( "\n" );
  1167.    exit( 0 );
  1168.    }
  1169. }
  1170. /**********************************************************************/
  1171. void near process_arguments( index, argc, argv, an_error )
  1172. int index, argc, an_error;
  1173. char **argv;
  1174. {
  1175. char c;
  1176. int i, tmp;
  1177.  
  1178. for( i = index; i < argc; ++i )
  1179.    {
  1180.    if( ( argv[ i ][ 0 ] == '/' ) || ( argv[ i ][ 0 ] == '-' ) )
  1181.       {
  1182.       c = (char)tolower( (int)argv[ i ][ 1 ] );
  1183.       switch( c )
  1184.          {
  1185.          case 'n':
  1186.             ibm_flag = ( ibm_flag )? false: true;
  1187.             break;
  1188.          case 'l':
  1189.             g_lib_flag = ( g_lib_flag )? false: true;
  1190.             break;
  1191.          case 'c':
  1192.             g_comment_flag = ( g_comment_flag )? false: true;
  1193.             break;
  1194.          case 'd':
  1195.             g_dec_def_flag = ( g_dec_def_flag )? false: true;
  1196.             break;
  1197.          case 's':
  1198.             stats_only = ( stats_only )? false: true;
  1199.             break;
  1200.          case 'q':
  1201.             g_quiet_flag = ( g_quiet_flag )? false: true;
  1202.             break;
  1203.          case 'o':
  1204.             g_ov_flag = true;
  1205.             break;
  1206.          case 'u':
  1207.             g_un_flag = true;
  1208.             break;
  1209.          case 'h':
  1210.             g_help_flag = true;
  1211.             break;
  1212.          case 'x':
  1213.             g_tech_flag = true;
  1214.             break;
  1215.          default:
  1216.           if( ( strlen( argv[ i ] ) > 3 ) && ( argv[ i ][ 2 ] == ':' ) )
  1217.               {
  1218.                tmp = atoi( &argv[ i ][ 3 ] );
  1219.                switch( c )
  1220.                   {
  1221.                   case 'p':
  1222.                    if( ( ( 50 < tmp ) && ( tmp < 256 ) ) || ( tmp == 0 ) )
  1223.                        defined_page_length = tmp;
  1224.                    break;
  1225.                   case 'm':
  1226.                      if( ( 0 <= tmp ) && ( tmp <= 30 ) )
  1227.                         defined_left_margin = tmp;
  1228.                      break;
  1229.                   case 'r':
  1230.                      if( ( 0 <= tmp ) && ( tmp <= 30 ) )
  1231.                         defined_right_margin = tmp;
  1232.                      break;
  1233.                   case 't':
  1234.                      (void)strcpy( target, &argv[ i ][ 3 ] );
  1235.                      target_flag = true;
  1236.                      break;
  1237.                   case 'w':
  1238.                      if( ( 79 < tmp ) && ( tmp < 256 ) )
  1239.                         defined_page_width = tmp;
  1240.                      break;
  1241.                   case 'f':
  1242.                      if( ( 1 < tmp ) && ( tmp < 5462 ) )
  1243.                         Max_functions = tmp;
  1244.                      break;
  1245.                   default:
  1246.                      (void)printf(
  1247.                          "\nUnknown argument character: %c, ignored!\n",
  1248.                            argv[ i ][ 1 ]
  1249.                               );
  1250.                      break;
  1251.                   }  /* end of switch on character after / or - */
  1252.                }     /* end of if :something */
  1253.             else
  1254.                (void)printf( "\nMissing : for argument %s, ignored!\n",
  1255.                              argv[ i ] );
  1256.             break;
  1257.          }           /* end of switch on character after / or - */
  1258.       }              /* end of if / or - */
  1259.    else
  1260.       (void)printf( "\nUnknown argument: %s, ignored!\n", argv[ i ] );
  1261.    }                 /* end of for loop on arguments */
  1262.  
  1263. if( g_tech_flag )
  1264.    {
  1265.    (void)printf( "\n" );
  1266.    (void)printf( "Notes: 1. Max recursive function displacement of %d.\n",
  1267.                  Max_Recursion
  1268.                );
  1269.    (void)printf(
  1270. "         2. Max # of unique function calls per defined function\n\
  1271.             for all defined functions is %d.\n",
  1272.    Max_functions );
  1273.    (void)printf( "         3. Max # of defined functions is %d.\n",
  1274.       Max_defined_functions );
  1275.    (void)printf( "\n" );
  1276.    (void)printf( "sizeof()\'s:\n" );
  1277.    (void)printf(
  1278. " function table = %u, contents = %u, data base = %u,\
  1279.  database = %u, lib = %u\n",
  1280.       sizeof( function_type ),
  1281.       sizeof( file_record_type ),
  1282.       sizeof( data_base_record_type ),
  1283.       sizeof( array_of_ptrs_to_records ),
  1284.       sizeof( sorted_called_list_ptrs )
  1285.                );
  1286.    (void)printf( "\n" );
  1287.    (void)printf(
  1288.    "The program will tend to show certain \'c\' functions as unused.\n" );
  1289.    (void)printf(
  1290.    "1. defined functions assigned to declared pointers to function names\n" );
  1291.    (void)printf(
  1292.    "   and executed as pointers to those function names won't be seen.\n" );
  1293.    (void)printf(
  1294.    "2. #if(s) controlling the generation of code especially with\n" );
  1295.    (void)printf(
  1296.    "   braces( { } ) in the conditional code section will especially\n" );
  1297.    (void)printf(
  1298.    "   screw up if there is an #else code part.  This program will work\n" );
  1299.    (void)printf(
  1300.    "   on both code parts of the conditional and most probably get out\n" );
  1301.    (void)printf(
  1302.    "   of sync with the braces. One might do a preprocessor pass compile\n" );
  1303.    (void)printf(
  1304.    "   and heave it\'s output files as input files at this program.\n" );
  1305.    (void)printf(
  1306.    "3. #define(s) that expand to functions and call functions will also\n" );
  1307.    (void)printf(
  1308.    "   be neglected.  The preprocessor may be used as stated above.\n" );
  1309. /******
  1310.    (void)printf(
  1311.    "\n" );
  1312. ******/
  1313.    (void)printf( "\n" );
  1314.    }
  1315.  
  1316. if( g_help_flag )
  1317.    {
  1318.    (void)printf( "\n" );
  1319.    (void)printf(
  1320.    "The listfile argument is an ascii text file containing the list of\n"
  1321.                );
  1322.    (void)printf(
  1323.    "filenames to process, one filename per line (optional overlay number.)\n"
  1324.                );
  1325.    (void)printf(
  1326.    "The output file may be a device or a filename. If there is no\n"
  1327.                );
  1328.    (void)printf(
  1329.    "output filename, \'prn\' is assumed. Note that one may put \'con\'\n"
  1330.                );
  1331.    (void)printf(
  1332.    "here and view the output of the program before printing or saving\n"
  1333.                );
  1334.    (void)printf(
  1335.    "to a filename.\n"
  1336.                );
  1337.    (void)printf(
  1338.    "Also note that the output filename and the input filenames in the\n"
  1339.                );
  1340.    (void)printf(
  1341.    "listfile may be full pathnames with drives and or paths.\n"
  1342.                );
  1343.    (void)printf( "/ arguments accept the alternate - form.\n" );
  1344.    (void)printf( "For example: cp x y -s, cp /h, cp x -x /d -t:junk\n" );
  1345.    (void)printf( "arguments may be in upper or lower case.\n" );
  1346.    (void)printf( "Note that the target function is case sensitive\n" );
  1347.    (void)printf( "since it is a \'c\' function name.\n" );
  1348.    (void)printf( "\n" );
  1349.    }
  1350. if( an_error )
  1351.    {
  1352.    if( g_help_flag || g_tech_flag )
  1353.       exit( 0 );
  1354.    else
  1355.       (void)printf( "Oops..." );
  1356.    }
  1357. }
  1358. /***********************************************************************/
  1359.  
  1360.  
  1361. [LISTING FOUR]
  1362.  
  1363. /***************************************************************************
  1364.                                    cpbuild.c
  1365. static void near mark_as_static( function_type *, char*, int );
  1366. static int near  test_and_add( function_type *, char *, int );
  1367. static void near unget_chars( char );
  1368. static char near get_chars( FILE * );
  1369. static char near get_to_next_possible_token( FILE * );
  1370. static int near  is_legal_identifier_character( char );
  1371.        int near  build_the_data_base( char * );
  1372. ***************************************************************************/
  1373.  
  1374. #define  MAIN  0
  1375. #include "cpheader.h"
  1376.  
  1377.        int near  build_the_data_base( char * );
  1378. static char near get_chars( FILE * );
  1379. static char near get_to_next_possible_token( FILE * );
  1380. static int near  is_legal_identifier_character( char );
  1381. static void near mark_as_static( function_type *, char*, int );
  1382. static int near  test_and_add( function_type *, char *, int );
  1383. static void near unget_chars( char );
  1384.  
  1385. /***************************************************************************/
  1386. static void near mark_as_static( ptr_to_function_list, 
  1387.                                  name_of_static_function, count
  1388.                                )
  1389. char *name_of_static_function;
  1390. function_type *ptr_to_function_list;
  1391. int count;
  1392. {
  1393. int i;
  1394.  
  1395. for( i = 0; i < count; ++i )
  1396.    {
  1397.    if(
  1398.       !strcmp( name_of_static_function, ptr_to_function_list->functions_name )
  1399.      )
  1400.       ptr_to_function_list->static_function = true;
  1401.    ++ptr_to_function_list;
  1402.    }
  1403. }
  1404. /***************************************************************************/
  1405. #define KEYS   7
  1406.  
  1407. static int near test_and_add( ptr_to_function_list, string, count )
  1408. function_type *ptr_to_function_list;
  1409. char *string;
  1410. int count;
  1411. {
  1412. int i, is_a_new_function_name;
  1413. static char *keywords[ KEYS ] =
  1414.    {  /* must catch do (void)printf, while(), else (void)... etc. ***/
  1415.    "do", "while", "if", "else", "for", "switch", "return"
  1416.    };
  1417.  
  1418. for( i = 0; ( i < KEYS ) && ( strcmp( string, keywords[ i ] ) != 0 ); ++i )
  1419.    ;
  1420. if( i < KEYS )
  1421.    is_a_new_function_name = false;     /* ie a reserved word match */
  1422. else                                   /* is a function name */
  1423.    {
  1424.    for( i = 0; i < count; ++i )
  1425.       {
  1426.       if( !strcmp( string, ptr_to_function_list->functions_name ) )
  1427.          {                       /* function name matches */
  1428.          if( !ptr_to_function_list->static_function )
  1429.             break;               /* and isn't static */
  1430.          else
  1431.             {
  1432.             if( !strcmp( ptr_to_function_list->its_filename,
  1433.                          file_record_array_ptr->source_filename
  1434.                       )
  1435.               )
  1436.                break;            /* only statics in same file match */
  1437.             }
  1438.          }
  1439.       ++ptr_to_function_list;
  1440.       }
  1441.    if( i == count )
  1442.       {                                /* new function name */
  1443.       is_a_new_function_name = true;   /* add function name to list */
  1444.       if( ( function_list_ptr->functions_name = strdup( string ) ) == NULL )
  1445.          {
  1446.          (void)fprintf( stderr, "Ran out of memory.\n" );
  1447.          exit( 1 );
  1448.          }
  1449.       function_list_ptr->static_function = false;
  1450.       function_list_ptr->its_filename =
  1451.          file_record_array_ptr->source_filename;
  1452.       function_list_ptr->is_referenced = 1;
  1453.  
  1454.       ++function_list_ptr;             /* point to next empty cell */
  1455.       ++count_of_functions;            /* increase current size */
  1456.       if( count_of_functions > Max_functions )
  1457.          {
  1458.          (void)fprintf( stderr, "Too many functions.\n" );
  1459.          exit( 1 );
  1460.          }
  1461.       }
  1462.    else                                /* string already in function list */
  1463.       {
  1464.       is_a_new_function_name = false;
  1465.       ptr_to_function_list->is_referenced++;
  1466.       }
  1467.    }
  1468. return is_a_new_function_name;
  1469. }
  1470. /***************************************************************************/
  1471. static void near unget_chars( c )
  1472. char c;
  1473. {
  1474. if( ( push_buffer_ptr - push_buffer ) < Max_unget_buffer )
  1475.    *push_buffer_ptr++ = c;
  1476. else
  1477.    {
  1478.    (void)fprintf( stderr, "\nProgram syntax error:" );
  1479.    (void)fprintf( stderr, " Too many pushed characters.\n" );
  1480.    exit( 1 );
  1481.    }
  1482. }
  1483. /***************************************************************************/
  1484. static char near get_chars( stream )
  1485. FILE * stream;
  1486. {
  1487. register char c;
  1488.  
  1489. if( push_buffer_ptr != push_buffer )
  1490.    c = *--push_buffer_ptr;
  1491. else
  1492.    {
  1493.    c = (char)fgetc( stream );
  1494.    if( c == EOF )
  1495.       c = Control_z;
  1496.    if( c == 0x0a )
  1497.       {
  1498.       file_record_array_ptr->line_count++;
  1499.       file_record_array_ptr->size++;           /* count the unseen <cr> */
  1500.       }
  1501.    file_record_array_ptr->size++;
  1502.    }
  1503. return c;
  1504. }
  1505. /***************************************************************************/
  1506. static char near get_to_next_possible_token( stream )
  1507. FILE *stream;
  1508. {
  1509. register char
  1510.    c;
  1511. char
  1512.    next_char_peek;
  1513. int
  1514.    done;
  1515.  
  1516. static int       /* the only apparent reason these are static is for speed */
  1517.    quotes_flag =           false,
  1518.    comment_flag =          false,
  1519.    escape_sequence_flag =  false,
  1520.    pound_sign_flag =       false,
  1521.    ascii_quote_flag =      false;
  1522. static int
  1523.    fp = 0;   /*****<<<<< */
  1524. static char *cp;
  1525.  
  1526. done = false;
  1527. do {
  1528.    c = get_chars( stream );
  1529.    if( c != Control_z )
  1530.       {   
  1531.       if( comment_flag )
  1532.          {
  1533. /**************************
  1534.    process /* comment sequence of characters
  1535. ***************************/
  1536.          if( first_comment == true )
  1537.             {
  1538.             if( fp < ( Max_general_buffers - 2 ) )
  1539.                {
  1540.                if(
  1541.                   ( c != '\n' ) &&
  1542.                   ( strlen( cp ) < effective_width )
  1543.                  )
  1544.                   {
  1545.                   file_comment_buffer[ fp++ ] = c;
  1546.                   file_comment_buffer[ fp ] = '\0';
  1547.                   }
  1548.                else        /* c == \n or length >= width */
  1549.                   {
  1550.                   file_comment_buffer[ fp++ ] = '\n';
  1551.                   file_comment_buffer[ fp ] = '\0';
  1552.                   cp = (char *)&file_comment_buffer[ fp ];
  1553.                   if( c != '\n' )
  1554.                      {
  1555.                      file_comment_buffer[ fp++ ] = c;
  1556.                      file_comment_buffer[ fp ] = '\0';
  1557.                      }
  1558.                   }
  1559.                }
  1560. /*          else     /* 1st comment exceeds buffer */
  1561.             }        /* end of if first_comment == true */
  1562.          if( c == '*' )
  1563.             {
  1564.             next_char_peek = get_chars( stream );
  1565.             if( next_char_peek == '/' )          /* close comment */
  1566.                {
  1567.                comment_flag = false;
  1568.                unget_chars( ' ' );  /* comments are white space in 'c' */
  1569.                if( first_comment == true )
  1570.                   {
  1571.                   first_comment = completed;
  1572.                   fp = 0;
  1573.                   cp = (char *)&file_comment_buffer[ fp ];
  1574.                   }
  1575.                }
  1576.             else        /* next_char_peek != '/' ie close comment */
  1577.                unget_chars( (char)next_char_peek );
  1578.             }  /* end of if c == '*' */
  1579.          }
  1580.       else     /* not /* */
  1581.          {
  1582. /**************************
  1583.    process \sequence character, hoping \" \' \\ etc inside " or '
  1584. ***************************/
  1585.          if( escape_sequence_flag )
  1586.             escape_sequence_flag = false;
  1587.          else     /* not /*, not \ */
  1588.             {
  1589. /**************************
  1590.    process " string sequence of characters
  1591. ***************************/
  1592.             if( quotes_flag )
  1593.                {
  1594.                if( c == '\\' )                  /* check for \'\n' */
  1595.                   {
  1596.                   next_char_peek = get_chars( stream );
  1597.                   if( next_char_peek != '\n' )  /* so not \'\n' */
  1598.                      {
  1599.                      escape_sequence_flag = true;
  1600.                      unget_chars( (char)next_char_peek );
  1601.                      }
  1602. /*******          else                          /* \'\n' continuation */
  1603.                   }
  1604.                else                             /* not \ */
  1605.                   if( c == '\"' )
  1606.                      quotes_flag = false;
  1607.                }
  1608.             else     /* not ", not /*, not \ */
  1609.                {
  1610. /**************************
  1611.    process ' ascii character sequence
  1612. ***************************/
  1613.                if( ascii_quote_flag )
  1614.                   {
  1615.                   if( c == '\\' )
  1616.                      escape_sequence_flag = true;
  1617.                   else
  1618.                      if( c == '\'' )
  1619.                         ascii_quote_flag = false;
  1620.                   }
  1621.                else  /* not ', not ", not /*, not \ */
  1622.                   {
  1623. /**************************
  1624.    process # sequence of characters, ie #if, #define, etc.
  1625.    define causes code sequencing problems it would seem!
  1626. ***************************/
  1627.                   if( pound_sign_flag )
  1628.                      {
  1629.                      if( c == '/' )       /* comments override #defines etc */
  1630.                         {
  1631.                         next_char_peek = get_chars( stream );
  1632.                         if( next_char_peek == '*' )
  1633.                            comment_flag = true;
  1634.                         else
  1635.                            unget_chars( (char)next_char_peek );
  1636.                         }
  1637.                      else
  1638.                         {
  1639.                         if( c == '\n' )
  1640.                            pound_sign_flag = false;
  1641.                         else                          /* c != \n */
  1642.                            {
  1643.                            if( c == '\\' )  /* check for \'\n' continuation */
  1644.                               {   
  1645.                               next_char_peek = get_chars( stream );
  1646.                               if( next_char_peek != '\n' ) /* it aint \'\n' */
  1647.                                  unget_chars( (char)next_char_peek );
  1648. /*                            else              /* \'\n' means continue # */
  1649.                               }
  1650.                            }
  1651.                         }
  1652.                      }
  1653.                   else     /* not ', not #, not ", not /*, not \ */
  1654.                      {
  1655. /**************************
  1656.    process anything else
  1657. ***************************/
  1658.                      done = false;     /* assume a ' or " or # or /* */
  1659.                      switch( c )
  1660.                         {
  1661.                         case '\"':
  1662.                            quotes_flag = true;
  1663.                            break;
  1664.                         case '\'':
  1665.                            ascii_quote_flag = true;
  1666.                            break;
  1667.                         case '#':
  1668.                            pound_sign_flag = true;
  1669.                            break;
  1670.                         case '/':
  1671.                            next_char_peek = get_chars( stream );
  1672.                            if( next_char_peek == '*' )
  1673.                               {
  1674.                               comment_flag = true;
  1675.                               if( first_comment == false )
  1676.                                  {           /* the 1st comment of the file */
  1677.                                  first_comment = true;
  1678.                                  fp = 0;
  1679.                                  cp = (char *)&file_comment_buffer[ fp ];
  1680.                                  }
  1681.                               }
  1682.                            else
  1683.                               {
  1684.                               unget_chars( (char)next_char_peek );
  1685.                               done = true;   
  1686.                               }
  1687.                            break;
  1688.                         default:       /* a worthy character to return */
  1689.                            done = true;   
  1690.                         }
  1691.                      }     /* end of else not ascii */
  1692.                   }        /* end of else not # */
  1693.                }           /* end of else not " */
  1694.             }              /* end of else not /* */
  1695.          }                 /* end of else not \ */
  1696.       }                    /* end of if c != Control_z */
  1697.    }
  1698. while( !done && ( c != Control_z ) );
  1699. if( c == Control_z )
  1700.    {
  1701.    ascii_quote_flag = false;
  1702.    pound_sign_flag = false;
  1703.    quotes_flag = false;
  1704.    escape_sequence_flag = false;
  1705.    comment_flag = false;
  1706.    fp = 0;
  1707.    }
  1708. return c;
  1709. }
  1710. /***************************************************************************/
  1711. static int near is_legal_identifier_character( c )
  1712. char c;
  1713. {
  1714. if(
  1715.    ( ( 'A' <= c ) && ( c <= 'Z' ) ) ||
  1716.    ( ( 'a' <= c ) && ( c <= 'z' ) ) ||
  1717.    ( ( '0' <= c ) && ( c <= '9' ) ) ||
  1718.    ( c == '_')
  1719.   )
  1720.    return true;
  1721. else
  1722.    return false;
  1723. }
  1724. /***************************************************************************/
  1725. #define  C_line_length  512
  1726. #define  C_identifier_length  80
  1727.  
  1728. int near build_the_data_base( the_filename )
  1729. char * the_filename;
  1730. {
  1731. static char fake_comment[ ] = "no room!";
  1732. int found_a_possible_function;
  1733. int brace_count, body_found;
  1734. int open_parenthesis, parenthesis_count;
  1735. int at_end_of_source_file;
  1736. int dummy_index, total_called_count;
  1737. int function_definition_flag, static_flag;
  1738. int analyze_buffer_flag = false;
  1739. char c;
  1740. char *function_name_buffer_ptr;
  1741. char function_name_buffer[ C_identifier_length ];
  1742. char look_ahead_buffer[ C_line_length + 1 ];
  1743. FILE *stream;
  1744. data_base_record_type *data_base_ptr, *starting_data_base_ptr;
  1745. function_type *starting_called_function_ptr;
  1746.  
  1747. if( !g_quiet_flag )
  1748.    {
  1749.    (void)printf( "Processing file: %-12s\n", the_filename );
  1750.    }
  1751. if( !( stream = fopen( the_filename, "r" ) ) )  /***** rt <<<<<<<<<< */
  1752.    {
  1753.    (void)printf( "Cant open %s\n", the_filename );
  1754.    return -1;
  1755.    }
  1756.  
  1757. push_buffer_ptr = push_buffer;         /* reset input character stack */
  1758.                                        /* add file name to data base */
  1759. if( !( file_record_array_ptr->source_filename = strdup( the_filename ) ) )
  1760.    {
  1761.    (void)printf( "Ran out of memory.\n" );
  1762.    exit( 1 );
  1763.    }
  1764.  
  1765. starting_called_function_ptr = function_list_ptr;
  1766. starting_data_base_ptr = data_base_array_ptr; /* mark start of defined list */
  1767.  
  1768. look_ahead_buffer[ 0 ] = '\0';
  1769.  
  1770. first_comment = false;
  1771. file_comment_buffer[ 0 ] = '\0';
  1772.  
  1773. file_record_array_ptr->line_count = 0;  /* clear it's variables */
  1774. file_record_array_ptr->size = 0l;
  1775.  
  1776. function_name_buffer_ptr = function_name_buffer;
  1777. function_name_buffer[ 0 ] = '\0';
  1778.  
  1779. static_flag = false;
  1780. found_a_possible_function = false;
  1781. open_parenthesis = false;
  1782. body_found = false;
  1783.  
  1784. brace_count = 0;
  1785. parenthesis_count = 0;
  1786.  
  1787. at_end_of_source_file = false;
  1788. while( !at_end_of_source_file )
  1789.    {
  1790.    c = get_to_next_possible_token( stream );
  1791.    switch( c )
  1792.       {
  1793.       case '{':
  1794.          ++brace_count;
  1795.          break;
  1796.       case '}':
  1797.          --brace_count;
  1798.          break;
  1799.       case Control_z:
  1800.          at_end_of_source_file = true;
  1801.          analyze_buffer_flag = true;
  1802.          break;
  1803.       case '(':
  1804.          if( !open_parenthesis )
  1805.             ++open_parenthesis;
  1806.          analyze_buffer_flag = true;
  1807.          break;
  1808.       case ' ':                  /* this is where we eat white space */
  1809.       case '\v':
  1810.       case '\b':
  1811.       case '\f':
  1812.       case '\t':
  1813.       case '\r':
  1814.       case '\n':
  1815.          do {
  1816.             c = get_to_next_possible_token( stream );
  1817.             }
  1818.          while(
  1819.                ( c == '\f' ) || ( c == ' ' ) || ( c == '\v' ) ||
  1820.                ( c == '\b' ) || ( c == '\t' ) || ( c == '\r' ) ||
  1821.                ( c == '\n' )
  1822.               );
  1823.          unget_chars( c ); /* put next non white character back */
  1824.  
  1825.          if( c != '(' )
  1826.             analyze_buffer_flag = true;
  1827. /***     else  /* c == '(' and next pass will find it */
  1828.          break;
  1829.       default:
  1830.          if( is_legal_identifier_character( c ) )
  1831.             {                          /* it's a good identifier character */
  1832.             *function_name_buffer_ptr++ = c;
  1833.             *function_name_buffer_ptr = '\0';
  1834.             }
  1835.          else                          /* it aint, so toss it */
  1836.             {
  1837.             if( static_flag && ( c == ';' ) )
  1838.                static_flag = false;
  1839. /*          if( c != '*' ) */
  1840.             analyze_buffer_flag = true;
  1841.             }
  1842.          break;
  1843.       }                    /* end of preliminary character parse */
  1844. /*****************
  1845.    start checking characters accumulated in function_name_buffer[]
  1846. ******************/
  1847.    if( analyze_buffer_flag )
  1848.       {
  1849.       analyze_buffer_flag = false;
  1850.       if(
  1851.          function_name_buffer[ 0 ] &&        /* ie not null string */
  1852.          (                                   /* & not number */
  1853.           ( function_name_buffer[ 0 ] < '0' ) ||
  1854.           ( function_name_buffer[ 0 ] > '9' )
  1855.          )
  1856.         )
  1857.          found_a_possible_function = true;
  1858.       else                                   /* it aint an identifier */
  1859.          {                                   /* so erase buffer */
  1860.          function_name_buffer_ptr = function_name_buffer;
  1861.          function_name_buffer[ 0 ] = '\0';
  1862.          if( static_flag && ( c == ';' ) )
  1863.             static_flag = false;
  1864.          open_parenthesis = false;
  1865.          }
  1866.       }                       /* end of analyze_buffer_flag */
  1867. /*****************
  1868.    if function_name_buffer[] has legal function name, scan ahead
  1869. ******************/
  1870.    if( found_a_possible_function )
  1871.       {
  1872.       found_a_possible_function = false;
  1873.       *function_name_buffer_ptr = '\0';   /* append nul char to end */
  1874.       if( !static_flag )                  /* don't retest if true */
  1875.          if( !strcmp( function_name_buffer, "static" ) )
  1876.             static_flag = true;
  1877.       if( open_parenthesis )
  1878.          {
  1879.          open_parenthesis = false;
  1880.          if( !brace_count )
  1881.             {                             /* ie outside any function body */
  1882.             parenthesis_count = 1;
  1883.             for( dummy_index = 0;
  1884.                  ( dummy_index < C_line_length ) && parenthesis_count;
  1885.                  ++dummy_index
  1886.                )
  1887.                {                          /* scan ahead for function() */
  1888.                c = get_to_next_possible_token( stream );
  1889.                if( c == Control_z )
  1890.                   break;            /* dummy_index not bumped */
  1891.                look_ahead_buffer[ dummy_index ] = c;
  1892.                look_ahead_buffer[ dummy_index + 1 ] = '\0';
  1893.                switch( c )
  1894.                   {
  1895.                   case '(':
  1896.                      ++parenthesis_count;
  1897.                      break;
  1898.                   case ')':
  1899.                      --parenthesis_count;
  1900.                      break;
  1901.                   }           /* dummy_index is bumped */
  1902.                }              /* end of for loop scanning for (...) */
  1903.             if( ( c == Control_z ) || ( !parenthesis_count ) )
  1904.                --dummy_index;
  1905.             function_definition_flag = false;
  1906.             for( ++dummy_index;
  1907.                  ( dummy_index < C_line_length ) && !function_definition_flag;
  1908.                  ++dummy_index
  1909.                )
  1910.                {                 /* what happens past (..) */
  1911.                c = get_to_next_possible_token( stream );
  1912.                if( c == Control_z )
  1913.                   break;            /* w/ function_definition_flag == false */
  1914.                look_ahead_buffer[ dummy_index ] = c;
  1915.                look_ahead_buffer[ dummy_index + 1 ] = '\0';
  1916.                switch( c )
  1917.                   {
  1918.                   case ' ':         /* this is where we eat white space */
  1919.                   case '\v':
  1920.                   case '\b':
  1921.                   case '\f':
  1922.                   case '\t':
  1923.                   case '\n':
  1924.                   case '\r':
  1925.                      break;
  1926.                   case '{':
  1927.                      ++body_found;
  1928.                      break;
  1929.                   case ';':
  1930.                   case ',':
  1931.                   case '(':            /* at (*)() type declaration */
  1932.                      if( !body_found )
  1933.                         {
  1934.                         function_definition_flag = true; /* declaration */
  1935.                         if( !g_quiet_flag )
  1936.                            {
  1937.                            if( g_dec_def_flag )
  1938.                               {
  1939.                               if( static_flag )
  1940.                                  (void)printf( " static" );
  1941.                               else
  1942.                                  (void)printf( "       " );
  1943.                               (void)printf( " declaration " );
  1944.                               (void)printf( "%s(%s\n",
  1945.                                             function_name_buffer,
  1946.                                             look_ahead_buffer );
  1947.                               }
  1948.                            }
  1949.                         }
  1950.                      break;
  1951.                   default:          /* any other non white character means */
  1952.                      function_definition_flag = completed;
  1953.                      if( !g_quiet_flag )
  1954.                         {
  1955.                         if( g_dec_def_flag )
  1956.                            {
  1957.                            if( static_flag )
  1958.                               (void)printf( "static " );
  1959.                            else
  1960.                               (void)printf( "       " );
  1961.                            (void)printf( "define " );
  1962.                            }   
  1963.                         }
  1964.                      break;
  1965.                   }           /* dummy_index is bumped */
  1966.                }              /* end of for loop parsing character after ) */
  1967.             body_found = false;
  1968.             if( function_definition_flag == false )
  1969.                {
  1970.                (void)printf( "\nSyntax error: " );
  1971.                (void)printf( "Function description.\n" );
  1972.                look_ahead_buffer[ dummy_index ] = '\0';
  1973.                (void)printf( "\n%s\n", look_ahead_buffer );
  1974.                exit( 1 );
  1975.                }
  1976.             while( dummy_index )
  1977.                {                       /* put all characters after ( back */
  1978.                unget_chars( look_ahead_buffer[ dummy_index - 1 ] );
  1979.                --dummy_index;
  1980.                }
  1981.             if( function_definition_flag == completed )
  1982.                {
  1983.                if( !g_quiet_flag )
  1984.                   {
  1985.                   if( g_dec_def_flag )
  1986.                      (void)printf( "%-40s\n", function_name_buffer );
  1987.                   }
  1988. /*******************
  1989.    this element can distinguish static functions
  1990.    in different files with the same name
  1991.  *******************/
  1992.                data_base_array_ptr->file_record_ptr = file_record_array_ptr;
  1993.                data_base_array_ptr->number_of_function_calls = 0;
  1994.                data_base_array_ptr->ptr_to_function_table = function_list_ptr;
  1995.                data_base_array_ptr->static_definition = static_flag;
  1996.                static_flag = false;
  1997.  
  1998.                if(
  1999.                   !( data_base_array_ptr->defined_function =
  2000.                      strdup( function_name_buffer )
  2001.                    )
  2002.                  )
  2003.                   {
  2004.                   (void)printf( "\nRan out of memory( for strdup() )." );
  2005.                   exit( 1 );
  2006.                   }
  2007.                data_base_array_ptr->number_of_references = 0;
  2008.                data_base_array_ptr->ptr_to_page_list = NULL;
  2009.  
  2010.                data_base_ptr = data_base_array_ptr; /* save current pointer */
  2011.                ++data_base_array_ptr;                 /* next entry */
  2012.                ++count_of_valid_records;
  2013.                if( count_of_valid_records > Max_defined_functions )
  2014.                   {
  2015.                   (void)printf( "\nToo many new functions\n" );
  2016.                   exit( 1 );
  2017.                   }
  2018.                }        /* end of function definition */
  2019.             static_flag = false;
  2020.             }
  2021.          else                    /* brace_count is not zero */
  2022.             {                    /* so inside a function */
  2023.             data_base_ptr->number_of_function_calls +=
  2024.                test_and_add( data_base_ptr->ptr_to_function_table,
  2025.                              function_name_buffer,
  2026.                              data_base_ptr->number_of_function_calls
  2027.                            );
  2028.             }
  2029.          look_ahead_buffer[ 0 ] = '\0';   /* reset tail buffer */
  2030.          static_flag = false;
  2031.          }                       /* end of parenthesis */
  2032.       function_name_buffer_ptr = function_name_buffer;   /* reset buffer */
  2033.       *function_name_buffer_ptr = '\0';
  2034.       }                    /* end of found_a_possible_function */
  2035.    }                       /* end of while !at_end_of_source_file */
  2036. (void)fclose( stream );
  2037. if( !g_quiet_flag )
  2038.    {
  2039.    (void)printf( "\n" );
  2040.    }
  2041.  
  2042. if(
  2043.    !( file_record_array_ptr->source_file_comment =
  2044.       strdup( file_comment_buffer )
  2045.     )
  2046.   )
  2047.     file_record_array_ptr->source_file_comment = fake_comment;
  2048.  
  2049. /***** mark called functions in list as static if in defined list *******/
  2050. total_called_count = 0;
  2051. data_base_ptr = starting_data_base_ptr;
  2052. while( data_base_ptr != data_base_array_ptr )
  2053.    {
  2054.    total_called_count += data_base_ptr->number_of_function_calls;
  2055.    ++data_base_ptr;
  2056.    }
  2057. data_base_ptr = starting_data_base_ptr;
  2058. while( data_base_ptr < data_base_array_ptr )
  2059.    {
  2060.    if( data_base_ptr->static_definition )
  2061.       mark_as_static( starting_called_function_ptr,
  2062.                       data_base_ptr->defined_function,
  2063.                       total_called_count
  2064.                     );
  2065.    ++data_base_ptr;
  2066.    }
  2067. ++file_record_array_ptr;      /* next file name entry */
  2068. ++count_of_source_files;
  2069. if( count_of_source_files >= Max_files )
  2070.    {
  2071.    (void)printf( "\nError: too many files to process.\n" );
  2072.    exit( 1 );
  2073.    }
  2074. return at_end_of_source_file;
  2075. }
  2076. /***************************************************************************/
  2077.  
  2078.  
  2079. [LISTING FIVE]
  2080.  
  2081. /***************************************************************************
  2082.                                   cpfuncts.c
  2083.        void near build_box_parts( int );
  2084.        void near tab_to_left_margin( FILE * );
  2085. static void near stop( void );
  2086. static void near setpage( data_base_record_type * );
  2087. static int  near recursion_check( char *, int );
  2088.        void near check_for_new_page( void );
  2089. static void near draw_output_block( char *, char *, char *,
  2090.                                     char *, int, int, int );
  2091.        int near  doprint( int );
  2092.        void near scan_for_static_or_global( int *, int, char *, char * );
  2093.        int near  binary_search_sorted_data_base( char * );
  2094.   
  2095.  ***************************************************************************/
  2096.  
  2097. #define  MAIN  0
  2098. #include "cpheader.h"
  2099.  
  2100. static char
  2101.    top_line_of_box[ 37 ], bottom_line_of_box[ 37 ],
  2102.    wall, ibm_line, bottom_attach,
  2103.    upper_left_corner, lower_left_corner,
  2104.    upper_right_corner, lower_right_corner,
  2105.    left_attach, right_attach;
  2106.  
  2107. static char *recursion_filename, *test_filename;
  2108. static int static_recursion;
  2109.  
  2110.        int near  binary_search_sorted_data_base( char * );
  2111.        void near build_box_parts( int );
  2112.        void near check_for_new_page( void );
  2113.        int near  doprint( int );
  2114.        void near scan_for_static_or_global( int *, int, char *, char * );
  2115.        void near tab_to_left_margin( FILE * );
  2116.  
  2117. static void near draw_output_block( char *, char *, char *,
  2118.                                     char *, int, int, int );
  2119. static int near  recursion_check( char *, int );
  2120. static void near stop( void );
  2121. static void near setpage( data_base_record_type * );
  2122.  
  2123. /***************************************************************************/
  2124. void near build_box_parts( is_ibm )
  2125. int is_ibm;
  2126. {
  2127. int i;
  2128.  
  2129. if( is_ibm )
  2130.    {
  2131.    wall =               '\xb3';
  2132.    ibm_line =           '\xc4';
  2133.    bottom_attach =      '\xc2';
  2134.    upper_left_corner =  '\xda';
  2135.    lower_left_corner =  '\xc0';
  2136.    upper_right_corner = '\xbf';
  2137.    lower_right_corner = '\xd9';
  2138.    left_attach =        '\xb4';
  2139.    right_attach =       '\xc3';
  2140.    }
  2141. else
  2142.    {
  2143.    wall =               '|';
  2144.    ibm_line =           '-';
  2145.    bottom_attach =      '+';
  2146.    upper_left_corner =  '+';
  2147.    lower_left_corner =  '+';
  2148.    upper_right_corner = '+';
  2149.    lower_right_corner = '+';
  2150.    left_attach =        '+';
  2151.    right_attach =       '+';
  2152.    }
  2153.  
  2154. top_line_of_box[ 0 ] = upper_left_corner;   
  2155. bottom_line_of_box[ 0 ] = lower_left_corner;
  2156. for( i = 1; i <= 34; ++i )
  2157.    {
  2158.    top_line_of_box[ i ] = ibm_line;
  2159.    bottom_line_of_box[ i ] = ibm_line;
  2160.    }
  2161. top_line_of_box[ i ] = upper_right_corner;
  2162. bottom_line_of_box[ i ] = lower_right_corner;
  2163. top_line_of_box[ ++i ] = '\0';
  2164. bottom_line_of_box[ i ] = '\0';
  2165. }
  2166. /***************************************************************************/
  2167. void near tab_to_left_margin( output )
  2168. FILE *output;
  2169. {
  2170. register int i;
  2171.  
  2172. for( i = 0; i < defined_left_margin; ++i )
  2173.    (void)fputc( ' ', output );
  2174. }
  2175. /***************************************************************************/
  2176. static void near stop()
  2177. {
  2178. (void)printf( "hello" );
  2179. }
  2180. /***************************************************************************/
  2181. static void near setpage( data_base_ptr )
  2182. data_base_record_type *data_base_ptr;
  2183. {
  2184. linked_pages_list *page_list_ptr;
  2185.  
  2186. page_list_ptr = data_base_ptr->ptr_to_page_list;
  2187. if( page_list_ptr == NULL )
  2188.    {
  2189.    if(
  2190.       !( page_list_ptr =
  2191.          (linked_pages_list *)malloc( sizeof( linked_pages_list ) )
  2192.        )
  2193.      )
  2194.       {
  2195.       (void)fprintf( stderr, "Ran out of memory for page # list.\n" );
  2196.       exit( 1 );
  2197.       }
  2198.  
  2199.    data_base_ptr->ptr_to_page_list = page_list_ptr;
  2200.    }
  2201. else
  2202.    {
  2203.    while( page_list_ptr->next_page_ptr )
  2204.       page_list_ptr = page_list_ptr->next_page_ptr;
  2205.  
  2206.    if(
  2207.       !( page_list_ptr->next_page_ptr =
  2208.          (linked_pages_list *)malloc( sizeof( linked_pages_list ) )
  2209.        )
  2210.      )
  2211.       {
  2212.       (void)fprintf( stderr, "Ran out of memory for page # list.\n" );
  2213.       exit( 1 );
  2214.       }
  2215.  
  2216.    page_list_ptr = page_list_ptr->next_page_ptr;
  2217.    }
  2218. page_list_ptr->next_page_ptr = NULL;
  2219. page_list_ptr->on_this_page = page - 1;
  2220. }
  2221. /***************************************************************************/
  2222. static int near recursion_check( string, static_call )
  2223. char *string;
  2224. int static_call;
  2225. {
  2226. register char **recursion_array_ptr;
  2227.  
  2228. recursion_array_ptr = recursion_array;
  2229. if( static_recursion )
  2230.    {                             /* defined function is static */
  2231.    while(
  2232.          *recursion_array_ptr && /* not null */
  2233.                                  /* and different function names */
  2234.          ( strcmp( *recursion_array_ptr, string ) ||
  2235.                                  /* or same function names and */
  2236.                                  /* in different files */
  2237.            strcmp( test_filename, recursion_filename )
  2238.          )
  2239.         )
  2240.    ++recursion_array_ptr;
  2241.    }
  2242. else
  2243.    {                             /* defined function is not static */
  2244.    while(
  2245.          *recursion_array_ptr && /* not null & */
  2246.                                  /* and different function names */
  2247.          ( strcmp( *recursion_array_ptr, string ) ||
  2248.                                  /* or same function names and */
  2249.            static_call           /* called is static */
  2250.          )
  2251.         )
  2252.       ++recursion_array_ptr;
  2253.    }
  2254. return ( *recursion_array_ptr )? true: false;
  2255. }
  2256. /***************************************************************************/
  2257. void near check_for_new_page()
  2258. {
  2259. int i;
  2260.  
  2261. if( defined_page_length == 0 && line == 9999 )
  2262.    {
  2263.    (void)fprintf( output, "\n\n\n\n" );
  2264.    line = 0;
  2265.    }
  2266. else
  2267.    {
  2268.    if( defined_page_length != 0 )
  2269.       {
  2270.       if( line > ( defined_page_length - 5 ) )
  2271.          {
  2272.          (void)fprintf( output, "\f" );
  2273.          line = 0;
  2274.          }
  2275.       if( line == 0 )
  2276.          {
  2277.          top_of_form_done = true;
  2278.          tab_to_left_margin( output );
  2279.          (void)fprintf( output, "%s", title );
  2280.          for( i = strlen( title ); i < ( effective_width - 10 ); ++i )
  2281.             (void)fputc( ' ', output );
  2282.          (void)fprintf( output, "Page:%4d\n", page );
  2283.          tab_to_left_margin( output );
  2284.          for( i = 0; i < effective_width; ++i )
  2285.             (void)fputc( '_', output );
  2286.          (void)fprintf( output, "\n\n" );
  2287.          line = 3;
  2288.          ++page;
  2289.          }
  2290.       }
  2291.    }
  2292. }
  2293. /***************************************************************************/
  2294. static void near draw_output_block( lead_in_string,
  2295.                                     name_of_function,
  2296.                                     description,
  2297.                                     name_of_file,
  2298.                                     either_count,
  2299.                                     tail_flag,
  2300.                                     kill_flag
  2301.                                   )
  2302. char *lead_in_string,
  2303.    *name_of_function,
  2304.    *description,
  2305.    *name_of_file;
  2306. int either_count, tail_flag, kill_flag;
  2307. {
  2308. unsigned int string_length;
  2309. static char alternate_lead_in[ 140 ];
  2310.  
  2311. /******* 1st line ***********************************************************/
  2312. tab_to_left_margin( output );
  2313. (void)fprintf( output, "%s %s\n", lead_in_string, top_line_of_box );
  2314.  
  2315. /******* 2nd line ***********************************************************/
  2316. tab_to_left_margin( output );
  2317. string_length = strlen( lead_in_string );
  2318. if( string_length )        /******* ie not main or defined function box ***/
  2319.    {
  2320.    (void)strncpy( alternate_lead_in, lead_in_string, --string_length );
  2321.    alternate_lead_in[ string_length++ ] = '\0'; /* restore string_length */
  2322.    }
  2323. if( string_length )        /******* ie not main or defined function box ***/
  2324.    (void)fprintf( output, "%s%c%c%c%-33s %c\n",
  2325.                   alternate_lead_in,
  2326. /***  if( kill_flag )      /****** last line to this box ******************/
  2327. /***  else                 /****** line continues downwards ***************/
  2328.                   ( kill_flag )? lower_left_corner: right_attach,
  2329.                   ibm_line, left_attach, name_of_function, wall );
  2330. else                       /****** main or defined box starting ***********/
  2331.    (void)fprintf( output,     "%c%c%-33s %c\n",
  2332.                   ibm_line, left_attach, name_of_function, wall );
  2333.  
  2334. /******* 3rd line ***********************************************************/
  2335. tab_to_left_margin( output );
  2336. if( string_length-- )      /***** kill outside vertical line on last box ****/
  2337.    lead_in_string[ string_length++ ] = ( kill_flag )? (char)' ': wall;
  2338. (void)fprintf( output, "%s %c%-20s %8s%3d  %c\n",
  2339.                lead_in_string, wall, description,
  2340.                name_of_file, either_count, wall );
  2341.  
  2342. /******* 4th line ***********************************************************/
  2343. tab_to_left_margin( output );
  2344. bottom_line_of_box[ 2 ] =  /******** if defined box has calls ***********/
  2345.    ( tail_flag && either_count )? bottom_attach: ibm_line;
  2346. (void)fprintf( output, "%s %s\n", lead_in_string, bottom_line_of_box );
  2347.  
  2348. line += 4;
  2349. top_of_form_done = false;
  2350. }
  2351. /***************************************************************************/
  2352. static char library_string[] = { "(library)" };
  2353. static char usage_string[] =   { "Used=" };
  2354. static char funct_string[] =   { "Functs=" };
  2355.  
  2356. int near doprint( index )
  2357. int index;
  2358. {
  2359. int
  2360.    loop_counter,
  2361.    max_count,
  2362.    starting_index,
  2363.    found,
  2364.    return_value;
  2365. data_base_record_type *record_ptr;
  2366. function_type *f_list_ptr;
  2367.  
  2368. static int kill_flag = false;
  2369.  
  2370. starting_index = index;
  2371. record_ptr = array_of_ptrs_to_records[ starting_index ];
  2372.  
  2373. recursion_array[ recursion_depth ] = record_ptr->defined_function;
  2374. if( !recursion_depth )
  2375.    {
  2376.    recursion_filename = record_ptr->file_record_ptr->source_filename;
  2377.                         /* add function to list for recursion check */
  2378.    static_recursion = record_ptr->static_definition;
  2379.    }
  2380. check_for_new_page();
  2381. setpage( array_of_ptrs_to_records[ starting_index ] );
  2382.  
  2383. return_value = page - 1;               /* must be a relic! */
  2384.                                        /* start w/ target function */
  2385. draw_output_block( nesting_display_buffer,
  2386.                    record_ptr->defined_function,
  2387.                    ( record_ptr->file_record_ptr )->source_filename,
  2388.                    funct_string,
  2389.                    record_ptr->number_of_function_calls,
  2390.                    true,
  2391.                    kill_flag
  2392.                  );
  2393.  
  2394. ++recursion_depth;
  2395.                            /****   mystic width = 4 *****/
  2396. (void)strcat( nesting_display_buffer, "   |" );
  2397. nesting_display_buffer[ strlen( nesting_display_buffer ) - 1 ] = wall;
  2398.  
  2399. max_count = record_ptr->number_of_function_calls;
  2400. for( loop_counter = 0, f_list_ptr = record_ptr->ptr_to_function_table;
  2401.      loop_counter < max_count;
  2402.      ++loop_counter, ++f_list_ptr
  2403.    )
  2404.    {
  2405.    kill_flag = ( loop_counter == ( max_count - 1 ) )? true: false;
  2406.    check_for_new_page();
  2407.                            /* is called function defined? */
  2408.    found = binary_search_sorted_data_base( f_list_ptr->functions_name );
  2409.    if( found >= 0 )
  2410.       {
  2411.       scan_for_static_or_global( &found,
  2412.                                  f_list_ptr->static_function,
  2413.                                  f_list_ptr->functions_name,
  2414.                                  f_list_ptr->its_filename
  2415.                                );
  2416.  
  2417.       }
  2418.    if( found >= 0 )        /* yes */
  2419.       {
  2420.       test_filename = f_list_ptr->its_filename;
  2421.       if( recursion_check( f_list_ptr->functions_name,
  2422.                            f_list_ptr->static_function )
  2423.         )
  2424.          {
  2425. /*         tab_to_left_margin( output );
  2426. /*         (void)fprintf( output, "%s\n", nesting_display_buffer ); */
  2427.          setpage( array_of_ptrs_to_records[ found ] );
  2428. /*         ++line; */
  2429.          top_of_form_done = false;
  2430.          draw_output_block( nesting_display_buffer,
  2431.                             f_list_ptr->functions_name,
  2432.                             "(recursive)",
  2433.                             "",
  2434.                             0,
  2435.                             false,
  2436.                             kill_flag
  2437.                           );
  2438.          }
  2439.       else        /* not recursive and found >= 0 */
  2440.          {
  2441.          if( array_of_ptrs_to_records[ found ]->number_of_references == 1 )
  2442.             {                       /* got a new function */
  2443. /*            tab_to_left_margin( output );
  2444. /*            (void)fprintf( output, "%s\n", nesting_display_buffer );
  2445. /*            ++line;
  2446. /*            top_of_form_done = false; */
  2447.             doprint( found );           /* used only once */
  2448.             }
  2449.          else
  2450.             {                       /* a previously defined function */
  2451. /*            tab_to_left_margin( output );
  2452. /*            (void)fprintf( output, "%s\n", nesting_display_buffer ); */
  2453.             setpage( array_of_ptrs_to_records[ found ] );
  2454. /*            ++line;
  2455. /*            top_of_form_done = false; */
  2456.             draw_output_block( nesting_display_buffer,
  2457.                                f_list_ptr->functions_name,
  2458.                                "(defined)",
  2459.                                usage_string,
  2460.                                f_list_ptr->is_referenced,
  2461.                                false,
  2462.                                kill_flag
  2463.                              ); 
  2464.             }
  2465.          }
  2466.       }
  2467.    else           /* found = -1 ie not defined means */
  2468.       {           /* a library function */
  2469. /*      tab_to_left_margin( output );
  2470. /*      (void)fprintf( output, "%s\n", nesting_display_buffer );
  2471. /*      ++line;
  2472. /*      top_of_form_done = false; */
  2473.       draw_output_block( nesting_display_buffer,
  2474.                          f_list_ptr->functions_name,
  2475.                          library_string,
  2476.                          usage_string,
  2477.                          f_list_ptr->is_referenced,
  2478.                          false,
  2479.                          kill_flag
  2480.                        );
  2481.       }
  2482.    }           /* end of loop on all called functions */
  2483.  
  2484.                            /* remove function f/ recursion list */
  2485. recursion_array[ recursion_depth ] = NULL;
  2486.                            /****   mystic width = 4 *****/
  2487. nesting_display_buffer[ strlen( nesting_display_buffer ) - 4 ] = '\0';
  2488. --recursion_depth;
  2489. return return_value;
  2490. }
  2491. /***************************************************************************/
  2492. void near scan_for_static_or_global(
  2493.                               index_ptr, is_static, function_name, file_name
  2494.                                    )
  2495. int *index_ptr, is_static;
  2496. char *function_name, *file_name;
  2497. {
  2498. int index;
  2499.  
  2500. index = *index_ptr;
  2501. if( index )
  2502.    while( index-- )
  2503.       if( strcmp( function_name,
  2504.                   array_of_ptrs_to_records[ index ]->defined_function )
  2505.         )
  2506.          {
  2507.          ++index;       /* exit at last matching defined function */
  2508.          break;
  2509.          }
  2510. do {
  2511.    if(
  2512.       ( !is_static && !array_of_ptrs_to_records[ index ]->static_definition
  2513.       ) ||
  2514.       ( is_static &&
  2515.         array_of_ptrs_to_records[ index ]->static_definition &&
  2516.         !strcmp( array_of_ptrs_to_records[ index ]->
  2517.                   file_record_ptr->source_filename,
  2518.                  file_name
  2519.                )
  2520.       )
  2521.      )
  2522.       break;
  2523.    }
  2524. while(
  2525.       ( ++index < count_of_functions ) &&
  2526.       !strcmp( function_name,
  2527.                array_of_ptrs_to_records[ index ]->defined_function
  2528.              )
  2529.      );
  2530. if(
  2531.    ( index >= count_of_functions ) ||
  2532.    strcmp( function_name, array_of_ptrs_to_records[ index ]->defined_function
  2533.          )
  2534.   )
  2535.    index = -1;
  2536. *index_ptr = index;
  2537. }
  2538. /***************************************************************************/
  2539. int near binary_search_sorted_data_base( key )
  2540. char *key;
  2541. {
  2542. int lo, hi, index;
  2543. int doesnt_match;
  2544.  
  2545. lo = 0;
  2546. hi = count_of_valid_records - 1;
  2547. index = ( hi - lo ) / 2;
  2548.  
  2549. while( true )
  2550.    {
  2551.    doesnt_match =
  2552.       strcmp( key, array_of_ptrs_to_records[ index ]->defined_function );
  2553.    if( !doesnt_match )        /* a match found at index */
  2554.       break;
  2555.    if( lo >= hi )             /* no match found */
  2556.       {
  2557.       index = -1;
  2558.       break;
  2559.       }
  2560.    if( doesnt_match < 0 )     /* key < choice so go downwards */
  2561.       hi = index - 1;
  2562.    else                       /* key > choice so go upwards */
  2563.       lo = index + 1;
  2564.    index = ( hi + lo ) / 2;   /* new choice */
  2565.    }
  2566. return index;
  2567. }
  2568. /***************************************************************************/
  2569.  
  2570.  
  2571. [LISTING SIX]
  2572.  
  2573. cp.obj : cp.c cpheader.h cp
  2574.         cl -AL -c cp.c
  2575.  
  2576. cpinput.obj : cpinput.c cpheader.h cp
  2577.         cl -AL -c cpinput.c
  2578.  
  2579. cpfuncts.obj : cpfuncts.c cpheader.h cp
  2580.         cl -AL -c cpfuncts.c
  2581.  
  2582. cpbuild.obj: cpbuild.c cpheader.h cp
  2583.         cl -AL cpbuild.c -c
  2584.  
  2585. cp.exe : cp.obj cpinput.obj cpfuncts.obj cpbuild.obj cp
  2586.         link cp+ cpinput+ cpbuild+ cpfuncts/packcode/st:16000,,cp;
  2587.  
  2588.  
  2589.  
  2590. [LISTING SEVEN]
  2591.  
  2592. cpheader.h
  2593. cp.c
  2594. cpbuild.c
  2595. cpfuncts.c
  2596. cpinput.c
  2597.  
  2598.  
  2599.